package com.ihr360.payroll.service.salaryreport.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ihr360.commons.exception.Ihr360Exception;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.model.type.FieldSource;
import com.ihr360.commons.model.type.SalaryFieldValueType;
import com.ihr360.payroll.dao.HistorySalaryPlanRepository;
import com.ihr360.payroll.entity.salary.SalaryReportPlanEntity;
import com.ihr360.payroll.entity.salary.reportsnapshot.AttendancePlanSnapShotEntity;
import com.ihr360.payroll.entity.salary.reportsnapshot.EnrollAdjustRuleSnapShotEntity;
import com.ihr360.payroll.entity.salary.reportsnapshot.PayrollConfigSnapShotEntity;
import com.ihr360.payroll.model.dto.salary.report.HistoryPayPeriod;
import com.ihr360.payroll.model.dto.salary.report.HistorySalaryPlan;
import com.ihr360.payroll.model.dto.salary.report.MergeSalaryReport;
import com.ihr360.payroll.model.dto.salary.report.embedded.AttendancePlanSnapshot;
import com.ihr360.payroll.model.dto.salary.report.embedded.PayrollConfigSnapshot;
import com.ihr360.payroll.model.dto.salary.report.embedded.SalaryFieldSnapshot;
import com.ihr360.payroll.model.response.salaryreport.SalaryHeader;
import com.ihr360.payroll.model.vo.SalaryFieldEntity;
import com.ihr360.payroll.request.salaryReport.SalaryReportRequest;
import com.ihr360.payroll.service.salaryreport.HistoryPayPeriodService;
import com.ihr360.payroll.service.salaryreport.HistorySalaryPlanService;
import com.ihr360.payroll.service.salaryreport.MergeSalaryReportService;
import com.ihr360.rest.reposity.SimpleRestReposity;
import com.ihr360.rest.service.AbstractSimpleRestServiceImpl;
import com.ihr360.shared.basicstaffinfo.dto.SyncedBasicStaffInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * Created by Eric on 2018/4/11/011.
 */
@Service
public class HistorySalaryPlanServiceImpl extends AbstractSimpleRestServiceImpl<HistorySalaryPlan, Long> implements HistorySalaryPlanService {

    public static final String EXCEL_FIELD_NAME = "姓名";
    public static final String EXCEL_FIELD_MOBILE_NO = "手机号";
    public static final String DEPARTMENT_NAME = "部门";

    @Autowired
    private HistorySalaryPlanRepository historySalaryPlanRepository;

    @Autowired
    private HistoryPayPeriodService historyPayPeriodService;

    @Autowired
    private MergeSalaryReportService mergeSalaryReportService;

    @Override
    public SimpleRestReposity<HistorySalaryPlan, Long> getSimpleRestReposity() {
        return historySalaryPlanRepository;
    }

    @Override
    public List<SalaryReportPlanEntity> getList(String companyId) {
        List<SalaryReportPlanEntity> result = Lists.newArrayList();
        List<HistorySalaryPlan> list = (List<HistorySalaryPlan>) this.getAllInCompany();
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        Map<Long, List<HistorySalaryPlan>> map = Maps.newHashMap();
        for (HistorySalaryPlan historySalaryPlan : list) {
            List<HistorySalaryPlan> tempList = map.get(historySalaryPlan.getSalaryPlanId());
            if (CollectionUtils.isEmpty(tempList)) {
                tempList = Lists.newArrayList();
            }
            tempList.add(historySalaryPlan);
            map.put(historySalaryPlan.getSalaryPlanId(), tempList);
        }
        for (Map.Entry<Long, List<HistorySalaryPlan>> entry : map.entrySet()) {
            List<HistorySalaryPlan> salaryPlanList = entry.getValue();
            int size = salaryPlanList.size();
            if (CollectionUtils.isEmpty(salaryPlanList)) {
                continue;
            }
            if (size == 1) {
                result.add(salaryPlanToEntity(salaryPlanList.get(0)));
            } else {
                //先将同一SalaryPlanId排序后取最新一条
                salaryPlanList.sort((o1, o2) -> {
                    if (o1.getCreatedAt() == null) {
                        return 1;
                    } else if (o2.getCreatedAt() == null) {
                        return -1;
                    } else {
                        return o2.getCreatedAt().compareTo(o1.getCreatedAt());
                    }
                });
                result.add(salaryPlanToEntity(salaryPlanList.get(0)));
            }
        }
        return result;
    }

    private SalaryReportPlanEntity salaryPlanToEntity(HistorySalaryPlan salaryPlan) {
        if (salaryPlan == null) {
            return null;
        }
        SalaryReportPlanEntity entity = new SalaryReportPlanEntity();
        entity.setName(salaryPlan.getName());
        entity.setSalaryPlanId(salaryPlan.getSalaryPlanId());
        entity.setEnableReport(false);
        PayrollConfigSnapshot payrollConfigSnapshot = salaryPlan.getPayrollConfig();
        if (payrollConfigSnapshot != null) {
            PayrollConfigSnapShotEntity payrollConfigSnapShotEntity = new PayrollConfigSnapShotEntity();
            BeanUtils.copyProperties(payrollConfigSnapshot, payrollConfigSnapShotEntity);
            entity.setPayrollConfig(payrollConfigSnapShotEntity);
        }
        AttendancePlanSnapshot attendancePlanSnapshot = salaryPlan.getAttendancePlan();
        if (attendancePlanSnapshot != null) {
            AttendancePlanSnapShotEntity attendancePlanSnapShotEntity = new AttendancePlanSnapShotEntity();
            BeanUtils.copyProperties(attendancePlanSnapshot, attendancePlanSnapShotEntity);
            if (attendancePlanSnapshot.getEnrollAdjustRuleSnapShot() != null) {
                EnrollAdjustRuleSnapShotEntity enrollAdjustRuleSnapShotEntity = new EnrollAdjustRuleSnapShotEntity();
                BeanUtils.copyProperties(attendancePlanSnapshot.getEnrollAdjustRuleSnapShot(), enrollAdjustRuleSnapShotEntity);
                attendancePlanSnapShotEntity.setEnrollAdjustRuleSnapShot(enrollAdjustRuleSnapShotEntity);
            }
            entity.setAttendancePlan(attendancePlanSnapShotEntity);
        }
        return entity;
    }

    @Override
    public List<HistorySalaryPlan> getListByMonthCycle(String companyId, Boolean monthCycle) {
        return historySalaryPlanRepository.findByCompanyIdAndMonthCycle(companyId, monthCycle);
    }

    @Override
    public List<HistorySalaryPlan> getListByIdList(String companyId, List<Long> ids) {
        return historySalaryPlanRepository.findByCompanyIdAndIdIn(companyId, ids);
    }

    @Override
    public List<SalaryFieldSnapshot> queryFieldList(String companyId, SalaryReportRequest reportRequest) {
        List<SalaryFieldSnapshot> list = Lists.newArrayList();
        if (reportRequest.getEnableReport() == null || !reportRequest.getEnableReport()) {//薪资报表
            HistorySalaryPlan historySalaryPlan = querySalaryPlan(companyId, reportRequest);
            if (historySalaryPlan == null || historySalaryPlan.getPayrollConfig() == null || CollectionUtils.isEmpty(historySalaryPlan.getPayrollConfig().getFields())) {
                return list;
            }
            list = historySalaryPlan.getPayrollConfig().getFields();
        } else {//合并报表
            MergeSalaryReport mergeSalaryReport = mergeSalaryReportService.getOne(reportRequest.getMergeReportId());
            if (mergeSalaryReport == null || mergeSalaryReport.getMergeSalaryField() == null) {
                return list;
            }
            list = mergeSalaryReport.getMergeSalaryField().getFields();
        }
        return list;
    }

    @Override
    public SalaryHeader queryStaffSalaryHead(String companyId, SalaryReportRequest reportRequest) {
        return getHead(querySalaryPlan(companyId, reportRequest));
    }

    @Override
    public SalaryHeader queryApprovalStaffSalaryHead(String companyId, Long historyPayPeriodId) {
        HistoryPayPeriod historyPayPeriod = historyPayPeriodService.getOne(historyPayPeriodId);
        if (historyPayPeriod == null) {
            throw new Ihr360Exception(null, "该薪资账期不存在");
        }
        return getHead(historyPayPeriod.getSalaryPlan());
    }

    private HistorySalaryPlan querySalaryPlan(String companyId, SalaryReportRequest reportRequest) {
        HistoryPayPeriod historyPayPeriod = historyPayPeriodService.getHistoryPayPeriod(companyId, reportRequest.getSalaryPlanId(), reportRequest.getTermDate());
        if (historyPayPeriod == null) {
            throw new Ihr360Exception(null, "该历史薪酬账期不存在");
        }
        return historyPayPeriod.getSalaryPlan();
    }

    /**
     * 解析表头
     */
    private SalaryHeader getHead(HistorySalaryPlan historySalaryPlan) {
        Map<String, SalaryFieldEntity> head = Maps.newLinkedHashMap();
        if (historySalaryPlan != null && historySalaryPlan.getPayrollConfig() != null && CollectionUtils.isNotEmpty(historySalaryPlan.getPayrollConfig().getFields())) {
            head.put(EXCEL_FIELD_NAME, new SalaryFieldEntity(EXCEL_FIELD_NAME, SyncedBasicStaffInfo.Field.staffName, true));
            head.put(DEPARTMENT_NAME, new SalaryFieldEntity(DEPARTMENT_NAME, SyncedBasicStaffInfo.Field.departmentName, true));
            head.put(EXCEL_FIELD_MOBILE_NO, new SalaryFieldEntity(EXCEL_FIELD_MOBILE_NO, SyncedBasicStaffInfo.Field.mobileNo, true));

            List<SalaryFieldSnapshot> salaryFields = historySalaryPlan.getPayrollConfig().getFields();
            salaryFields.forEach(field -> {
                SalaryFieldEntity entity = new SalaryFieldEntity();
                entity.setFieldName(field.getName());
                entity.setColumnName(field.getCode());
                entity.setSource(field.getSource());
                entity.setReadOnly(field.getSource() != FieldSource.INPUT);
                entity.setFormula(field.getFormula());
                SalaryFieldValueType type = field.getValueType();
                switch (type) {
                    case NUMBER:
                        entity.setType("DOUBLE");
                        break;
                    case DATE:
                    case TIME:
                    case DATETIME:
                        entity.setType("DATE");
                        entity.setRegexp(type.getPattern());
                        break;
                    case ARRAY:
                        break;
                    default:
                        entity.setType("STRING");
                        break;
                }
                head.put(entity.getFieldName(), entity);
            });
        }
        SalaryHeader salaryHeader = new SalaryHeader();
        salaryHeader.setHeadMap(head);
        return salaryHeader;
    }
}
